﻿/****************************************************
	文件：AgentBase.cs
	作者：林文豪
	日期：2021/03/21 18:37:27
	功能：1、实现IAgent接口
         2、每个Npc身上都应该有一个AgentBase，这个脚本用于存储所有的动作、目标，存储规划器等等
*****************************************************/

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using MyGame.Character;
using MyGame.Global;
using UnityEngine.UI;

namespace MyGame.AI.GOAP {
    public class AgentBase : IAgent {
        private Enemy    _Owner;    // 拥有者
        private PlannerWithMultiwayTree _Planner;  // 规划器

        private List<IGoal>  _PossibleGoals;    // 所有可能的目标列表
        private IGoal        _MostPossibleGoal; // 最可能的目标
        private Queue<INode> _CurrentPlan;      // 当前计划

        private List<IGoal>   _AllGoals;        // 所有目标
        private List<IAction> _AllActions;      // 所有动作

        public PlannerWithMultiwayTree Planner => _Planner;

        public AgentBase(Enemy owner) {
            _Owner   = owner;
            // 读表获取动态生成Goals与Actions
            GetActionsAndGoalsFromData(owner);
            // 采用多叉树用于存储所有通路
            _Planner = GoapFactory.Instance.GeneratePlanner(owner);
        }

        public void FrameFunc() {
            // TODO ： 这里更新的是Action的实际效果，例如：移动、攻击等等
            // 如果当前列表中存在动作结点，那么就指定动作
            // if (_CurrentPlan.Count > 0) {
            //     _CurrentPlan.Peek().FrameFunc();
            // }
            // // 如果不存在，那么就寻找优先级最高的目标，进行重新规划
            // else {
            //     IGoal mostPossibleGoal = GetMostPossibleGoal();
            //     RePlanningWhenCurPlanClear(mostPossibleGoal);
            // }
        }

        // TODO : 未完成
        public bool TryReplanningToGoal(IGoal goal) {
            return true;
        }

        // 自动重新规划，当此Ag
        protected void RePlanningWhenCurPlanClear(IGoal goal) {
            List<IAction> plan = _Planner.GetPlan(goal);
            for (int i = 0; i < plan.Count; i++) {
                // TODO : 临时写法，需要更改
                (plan[i] as ActionBase).OnFinish += (result)=>_CurrentPlan.Dequeue();
                _CurrentPlan.Enqueue(plan[i]);
            }
        }

        // TODO : 需要 IGoal 实现 IComparable 接口
        protected IGoal GetMostPossibleGoal() {
            _PossibleGoals.Sort();
            return _PossibleGoals[0];
        }

        // TODO : 读表，获取指定敌人所拥有的Goal和Action
        private void GetActionsAndGoalsFromData(Enemy target) {
            _AllGoals   = new List<IGoal>();
            _AllActions = new List<IAction>();
            foreach (var goalType in target.Goals) {
                _AllGoals.Add(GoapFactory.Instance.GenerateGoal(goalType,_Owner));
            }
            foreach (var actionType in target.Actions) {
                _AllActions.Add(GoapFactory.Instance.GenerateAction(actionType,_Owner));
            }
        }
    }
}
